package com.hengpeng.itfin.service.impl;

import java.util.Date;
import java.util.List;

import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.hengpeng.common.exception.ServiceResult;
import com.hengpeng.common.exception.ServiceResultFactory;
import com.hengpeng.common.persist.entity.AbstractEntity.BoolValue;
import com.hengpeng.common.persist.query.DynamicQuery;
import com.hengpeng.common.util.DateTimeUtil;
import com.hengpeng.itfin.common.Configuration;
import com.hengpeng.itfin.exception.TransException;
import com.hengpeng.itfin.service.PaymentService;
import com.hengpeng.itfin.tools.PoolServer;
import com.hengpeng.itfinbase.constants.RespCodeConstants;
import com.hengpeng.itfinbase.constants.TransCodeConstants;
import com.hengpeng.itfinbase.en.AccountType;
import com.hengpeng.itfinbase.idAssign.ID;
import com.hengpeng.itfinbase.message.partner.CashRequestMsg;
import com.hengpeng.itfinbase.message.partner.CashResponseMsg;
import com.hengpeng.itfinbase.message.partner.DrawReconciliationRequestMsg;
import com.hengpeng.itfinbase.message.partner.DrawReconciliationResponseMsg;
import com.hengpeng.itfinbase.message.partner.DrawReconciliationResponseMsg.CashReconciliationDto;
import com.hengpeng.itfinbase.message.partner.PartnerTransType;
import com.hengpeng.itfinbase.message.partner.PayRequestMsg;
import com.hengpeng.itfinbase.message.partner.PayResponseMsg;
import com.hengpeng.itfinbase.message.partner.SaveReconciliationRequestMsg;
import com.hengpeng.itfinbase.message.partner.SaveReconciliationResponseMsg;
import com.hengpeng.itfinbase.message.partner.SaveReconciliationResponseMsg.SaveReconciliationDto;
import com.hengpeng.itfinbase.persist.Account;
import com.hengpeng.itfinbase.persist.AccountLog;
import com.hengpeng.itfinbase.persist.AccountLog.TransType;
import com.hengpeng.itfinbase.persist.Payment;
import com.hengpeng.itfinbase.persist.Payment.PayStatus;
import com.hengpeng.itfinbase.persist.Payment.PaymentType;
import com.hengpeng.itfinbase.persist.UserBankCard;
import com.hengpeng.itfinbase.persist.UserInfo;

/**
 * <pre>
 * 支付系统服务实现
 * </pre>
 * @author zhaojitao
 * @version 1.0, 2015-6-4
 */
@Service
@Lazy
@Transactional
public class PaymentServiceImpl extends BaseServiceImpl implements PaymentService
{
	@Override
	public void packPayRequest(PayRequestMsg request) {
		if (!serviceFactory.getPartnerService().isTrustPattern()) {
			// 设置测试金额
			String isPayTest = Configuration.getValue("pay.test");
			String testMoney = Configuration.getValue("pay.money");
			if (isPayTest != null && testMoney != null && isPayTest.equals("true")) {
				request.setTransAmt(testMoney);
			}
		}
		Payment payment = new Payment();
		payment.setType(PaymentType.IMPREST);
		payment.setProviderId(request.getProviderId());
		if (request.getAccountType() == AccountType.PLATFORM) {// 平台充值
			String orderId = ID.getInstanse().getID(18).toString();
			UserInfo user = serviceFactory.getDaoFactory().getUserInfoDao().get(request.getUserId());
			if (user == null) {
				throw new TransException("用户不存在！");
			}
			request.setOrdId(orderId);
			request.setOrdDate(DateTimeUtil.formatToStr(new Date(), DateTimeUtil.DATE_FORMAT_YYYYMMDD));
			request.setUsrCustId(user.getTrustAccountId());
		} else {
			UserInfo user = serviceFactory.getDaoFactory().getUserInfoDao().get(request.getUserId());
			if (user == null) {
				throw new TransException("用户不存在！");
			}
			Account account = serviceFactory.getAccountService().getAccount(user.getId());
			String orderId = ID.getInstanse().getID(18).toString();
			request.setOrdId(orderId);
			request.setOrdDate(DateTimeUtil.formatToStr(new Date(), DateTimeUtil.DATE_FORMAT_YYYYMMDD));
			request.setUsrCustId(user.getTrustAccountId());
			Double doubleMoney = Double.parseDouble(request.getTransAmt()) * 100;
			payment.setMoney(doubleMoney.longValue());
			payment.setUserId(request.getUserId());
			payment.setAccountType(request.getAccountType());
			payment.setCreateTime(new Date());
			payment.setIsReconcil(BoolValue.NO);
			payment.setOrderId(orderId);
			payment.setRequestTime(new Date());
			payment.setStatus(PayStatus.PAYING);
			payment.setTrustAccountId(request.getUsrCustId());
			payment.setUserAgent(request.getUserAgent());
			payment.setUserName(user.getUserName());
			payment.setAccountId(account.getId());
		}
		serviceFactory.getDaoFactory().getCommonDao().saveEntity(payment);
	}

	@Override
	public ServiceResult<Payment> dealPayResult(PayResponseMsg msg) {
		Payment payment = serviceFactory.getPaymentService().findByOrderId(msg.getOrdId());
		if (payment != null) {
			if (payment.getStatus() == PayStatus.PAYING) {
				if (msg.getRespCode().equals(RespCodeConstants.CommonCode.TRANS_SUC)) {
					Double feeAmt = Double.parseDouble(msg.getFeeAmt().replaceAll(",", "")) * 100;
					int i = serviceFactory.getDaoFactory().getPaymentDao().updateStatus(PayStatus.PAYING, PayStatus.SUCCESS, new Date(),
							new Date(), feeAmt.longValue(), msg.getOrdId());
					if (i > 0) {
						serviceFactory.getAccountService()
						.add(payment.getUserId(), TransType.IMPREST,
								Long.parseLong(String.valueOf(payment.getMoney())),
								String.valueOf(payment.getId()), "充值成功");
					}
//					UserInfo user = serviceFactory.getUserInfoService().getUserByTrustAccountId(msg.getFeeCustId());
//					if (feeAmt > 0d)
//					{
//						serviceFactory.getAccountService().changeAccountMoney(user.getId(), feeAmt.longValue(),
//								TransType.IMPREST_FEE, AccountLog.TradeMode.SUBTRACT, payment.getId().toString(),
//								"充值手续费");
//					}
				} else {
					serviceFactory.getDaoFactory().getPaymentDao().updateStatus(PayStatus.PAYING, PayStatus.FAILED, new Date(),
							new Date(), 0l, msg.getOrdId());
				}
			}
			return ServiceResultFactory.getServiceResult(RespCodeConstants.CommonCode.TRANS_SUC, payment);
		} else {
			// 未找到充值记录
			return ServiceResultFactory.getServiceResult(RespCodeConstants.CommonCode.DATA_NOT_FOUND, Payment.class);
		}
	}

	@Override
	public void packDrawRequest(CashRequestMsg request) {
		Payment payment = new Payment();
		payment.setType(PaymentType.DRAW);
		payment.setProviderId(request.getProviderId());
		if (request.getAccountType() == AccountType.PLATFORM) {
			// 平台取现，暂不记录本地记录
			UserInfo user = serviceFactory.getDaoFactory().getUserInfoDao().get(request.getUserId());
			if (user == null) {
				throw new TransException("用户不存在！");
			}
			String orderId = ID.getInstanse().getID(18).toString();
			request.setOrdId(orderId);
			request.setOrdDate(DateTimeUtil.formatToStr(new Date(), DateTimeUtil.DATE_FORMAT_YYYYMMDD));
			request.setUsrCustId(user.getTrustAccountId());
		} else {
			UserInfo user = serviceFactory.getDaoFactory().getUserInfoDao().get(request.getUserId());
			if (user == null) {
				throw new TransException("用户不存在！");
			}
			if (!serviceFactory.getPartnerService().isTrustPattern()) {
				UserBankCard bankCard = serviceFactory.getPersistService().get(UserBankCard.class,request.getBankCardId());
				if (bankCard == null) {
					throw new TransException("银行卡不存在！");
				}
				payment.setBankName(bankCard.getBankName().getText());
			}
			Double doubleMoney = Double.parseDouble(request.getTransAmt()) * 100;
			Account account = serviceFactory.getAccountService().getAccount(user.getId());
			if (account.getBaseMoney() - account.getFreezeMoney() < doubleMoney) {
				throw new TransException("金额不足！");
			}
			String orderId = ID.getInstanse().getID(18).toString();
			request.setOrdId(orderId);
			request.setOrdDate(DateTimeUtil.formatToStr(new Date(), DateTimeUtil.DATE_FORMAT_YYYYMMDD));
			request.setUsrCustId(user.getTrustAccountId());
			payment.setMoney(doubleMoney.longValue());
			payment.setUserId(request.getUserId());
			payment.setAccountType(request.getAccountType());
			payment.setCreateTime(new Date());
			payment.setIsReconcil(BoolValue.NO);
			payment.setOrderId(orderId);
			payment.setRequestTime(new Date());
			payment.setStatus(PayStatus.PAYING);
			payment.setTrustAccountId(request.getUsrCustId());
			payment.setUserAgent(request.getUserAgent());
			payment.setUserName(user.getUserName());
			payment.setAccountId(account.getId());
			serviceFactory.getDaoFactory().getCommonDao().saveEntity(payment);
			serviceFactory.getAccountService().freeze(payment.getUserId(), AccountLog.TransType.DRAW,
					Long.parseLong(String.valueOf(payment.getMoney())), String.valueOf(payment.getId()), "提现冻结");
		}
	}

	@Override
	public ServiceResult<Payment> dealDrawResult(CashResponseMsg msg) {
		Payment payment = serviceFactory.getPaymentService().findByOrderId(msg.getOrdId());
		if (payment != null) {
			if (payment.getStatus() == PayStatus.PAYING) {
				if (msg.getRespCode().equals(RespCodeConstants.CommonCode.TRANS_SUC)) {
					Double feeAmt = Double.parseDouble(msg.getFeeAmt().replaceAll(",", "")) * 100;
					int i = serviceFactory.getDaoFactory().getPaymentDao().updateStatus(PayStatus.PAYING, PayStatus.SUCCESS,
							new Date(), new Date(), feeAmt.longValue(), msg.getOrdId());
					if (i > 0) {
						serviceFactory.getAccountService().unfreezeForSuc(payment.getUserId(), AccountLog.TransType.DRAW,
								Long.parseLong(String.valueOf(payment.getMoney())),
								String.valueOf(payment.getId()), "提现成功");

						UserInfo user = serviceFactory.getUserInfoService().getUserByTrustAccountId(msg.getFeeCustId());
						if (feeAmt > 0d) {
							serviceFactory.getAccountService().changeAccountMoney(user.getId(), feeAmt.longValue(),
									AccountLog.TransType.DRAW_FEE, AccountLog.TradeMode.SUBTRACT,
									String.valueOf(payment.getId()), "提现手续费");
						}
					}
				} else if (msg.getRespCode().equals(RespCodeConstants.CommonCode.TRANSMESSAGE_ERRCODE_DEALING)) {// 处理中

				} else if (msg.getRespCode().equals(RespCodeConstants.AccountCode.CASH_ERRCODE_FAIL)) {// 失败
					int i = serviceFactory.getDaoFactory().getPaymentDao().updateStatus(PayStatus.PAYING, PayStatus.FAILED,
							new Date(), new Date(), 0l, msg.getOrdId());
					if (i > 0) {
						serviceFactory.getAccountService().unfreezeForFail(payment.getUserId(), AccountLog.TransType.DRAW,
								Long.parseLong(String.valueOf(payment.getMoney())), String.valueOf(payment.getId()),
								"提现失败解冻");
					}
				}
			}
			return ServiceResultFactory.getServiceResult(RespCodeConstants.CommonCode.TRANS_SUC, payment);
		} else {
			// 未找到充值记录
			return ServiceResultFactory.getServiceResult(RespCodeConstants.CommonCode.DATA_NOT_FOUND, Payment.class);

		}
	}

	@Override
	public Payment findByOrderId(String orderId)
	{
		DynamicQuery query = new DynamicQuery(Payment.class);
		query.eq("orderId", orderId);
		return serviceFactory.getPersistService().getByDynamicQuery(Payment.class, query);
	}

	@Override
	public Payment findByOrderIdAndProviderId(String orderId, String providerId)
	{
		DynamicQuery query = new DynamicQuery(Payment.class);
		query.eq("orderId", orderId);
		query.eq("providerId", providerId);
		return serviceFactory.getPersistService().getByDynamicQuery(Payment.class, query);
	}

	@Override
	public void saveReconciliation(Integer pageNum, Integer pageSize, Date beginDate, Date endDate)
	{
		SaveReconciliationResponseMsg responseMsg = serviceFactory.getPaymentService().doSaveReconciliation(pageNum,
				pageSize, beginDate, endDate);
		Integer totalItems = Integer.parseInt(responseMsg.getTotalItems());
		if (totalItems != null && (pageNum * pageSize) > totalItems)
		{
			saveReconciliation(pageNum + 1, pageSize, beginDate, endDate);
		}
		else
		{
			return;
		}
	}

	@Override
	public SaveReconciliationResponseMsg doSaveReconciliation(Integer pageNum, Integer pageSize, Date beginDate,
			Date endDate)
	{
		SaveReconciliationRequestMsg reqMsg = new SaveReconciliationRequestMsg();
		reqMsg.setBeginDate(DateTimeUtil.formatToStr(beginDate, DateTimeUtil.DATE_FORMAT_YYYYMMDD));
		reqMsg.setEndDate(DateTimeUtil.formatToStr(endDate, DateTimeUtil.DATE_FORMAT_YYYYMMDD));
		reqMsg.setPageNum(pageNum.toString());
		reqMsg.setPageSize(pageSize.toString());
		reqMsg.setPartnerTransType(PartnerTransType.SaveReconciliation);
		reqMsg.setTransType(TransCodeConstants.PartnerTransCode.REQUEST);
		SaveReconciliationResponseMsg responseMsg = (SaveReconciliationResponseMsg) serviceFactory.getPartnerService()
				.request(reqMsg);
		/**
		 * 处理结果
		 */
		List<SaveReconciliationDto> reconciliationInfos = responseMsg.getSaveReconciliationDtoList();
		if (reconciliationInfos != null && reconciliationInfos.size() > 0)
		{
			PoolServer poolServer = new PoolServer(50);
			for (SaveReconciliationDto dto : reconciliationInfos)
			{
				final PayResponseMsg payResponseMsg = new PayResponseMsg();
				payResponseMsg.setOrdId(dto.getOrdId());
				if ("S".equals(dto.getTransStat()))
				{// 成功
					payResponseMsg.setRespCode(RespCodeConstants.CommonCode.TRANS_SUC);
					payResponseMsg.setRespDesc(RespCodeConstants.CommonCode.TRANS_SUC_MSG);
				}
				else if ("F".equals(dto.getTransStat()))
				{// 失败
					payResponseMsg.setRespCode(RespCodeConstants.CommonCode.TRANS_FAIL);
					payResponseMsg.setRespDesc(RespCodeConstants.CommonCode.TRANS_FAIL_MSG);
				}
				else if ("I".equals(dto.getTransStat()))
				{// 初始
					/**
					 * 初始状态：用户还没有输入密码确认的充值 初始状态暂不处理
					 */
				}
				poolServer.executeTask(new Runnable()
				{
					@Override
					public void run()
					{
						serviceFactory.getPaymentService().dealPayResult(payResponseMsg);
					}
				});
			}
			poolServer.endServer();
		}
		return responseMsg;
	}

	@Override
	public void drawReconciliation(Integer pageNum, Integer pageSize, Date beginDate, Date endDate)
	{
		DrawReconciliationResponseMsg responseMsg = serviceFactory.getPaymentService().doDrawReconciliation(pageNum,
				pageSize, beginDate, endDate);
		Integer totalItems = Integer.parseInt(responseMsg.getTotalItems());
		if (totalItems != null && (pageNum * pageSize) > totalItems)
		{
			drawReconciliation(pageNum + 1, pageSize, beginDate, endDate);
		}
		else
		{
			return;
		}
	}

	@Override
	public DrawReconciliationResponseMsg doDrawReconciliation(Integer pageNum, Integer pageSize, Date beginDate,
			Date endDate)
	{
		DrawReconciliationRequestMsg reqMsg = new DrawReconciliationRequestMsg();
		reqMsg.setBeginDate(DateTimeUtil.formatToStr(beginDate, DateTimeUtil.DATE_FORMAT_YYYYMMDD));
		reqMsg.setEndDate(DateTimeUtil.formatToStr(endDate, DateTimeUtil.DATE_FORMAT_YYYYMMDD));
		reqMsg.setPageNum(pageNum.toString());
		reqMsg.setPageSize(pageSize.toString());
		reqMsg.setPartnerTransType(PartnerTransType.CashReconciliation);
		reqMsg.setTransType(TransCodeConstants.PartnerTransCode.REQUEST);
		DrawReconciliationResponseMsg responseMsg = (DrawReconciliationResponseMsg) serviceFactory.getPartnerService()
				.request(reqMsg);
		/**
		 * 处理结果
		 */
		List<CashReconciliationDto> reconciliationInfos = responseMsg.getCashReconciliationDtoList();
		if (reconciliationInfos != null && reconciliationInfos.size() > 0)
		{
			PoolServer poolServer = new PoolServer(50);
			for (CashReconciliationDto dto : reconciliationInfos)
			{
				final CashResponseMsg cashResponseMsg = new CashResponseMsg();
				cashResponseMsg.setOrdId(dto.getOrdId());
				if ("S".equals(dto.getTransStat()))
				{// 成功
					cashResponseMsg.setRespCode(RespCodeConstants.CommonCode.TRANS_SUC);
					cashResponseMsg.setRespDesc(RespCodeConstants.CommonCode.TRANS_SUC_MSG);
				}
				else if ("F".equals(dto.getTransStat()))
				{// 失败
					cashResponseMsg.setRespCode(RespCodeConstants.AccountCode.CASH_ERRCODE_FAIL);
				}
				else if ("I".equals(dto.getTransStat()))
				{// 初始
					cashResponseMsg.setRespCode(RespCodeConstants.CommonCode.TRANSMESSAGE_ERRCODE_DEALING);
				}
				else if ("H".equals(dto.getTransStat()))
				{// 经办
					cashResponseMsg.setRespCode(RespCodeConstants.CommonCode.TRANSMESSAGE_ERRCODE_DEALING);
				}
				else if ("R".equals(dto.getTransStat()))
				{// 拒绝
					cashResponseMsg.setRespCode(RespCodeConstants.AccountCode.CASH_ERRCODE_FAIL);
				}
				poolServer.executeTask(new Runnable() {
					@Override
					public void run() {
						serviceFactory.getPaymentService().dealDrawResult(cashResponseMsg);
					}
				});
			}
			poolServer.endServer();
		}
		return responseMsg;
	}
}
